package ar.edu.unlu.sistemas.p2p.business.task;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;

import ar.edu.unlu.sistemas.p2p.business.util.Logger;

public class TaskController {

	private HashMap<String,Task> tasks = new HashMap<String, Task>();
	private Set<String> tasksHistory = new HashSet<String>();
	private static TaskController INSTANCE = new TaskController();
	
	private TaskController() {
		
	}
	
	private Set<String> getTasksHistory() {
		return tasksHistory;
	}

	private void setTasksHistory(Set<String> tasksHistory) {
		this.tasksHistory = tasksHistory;
	}

	public static TaskController getInstance() {
		return INSTANCE;
	}

	private HashMap<String, Task> getTasks() {
		return tasks;
	}

	private void setTasks(HashMap<String, Task> tasks) {
		this.tasks = tasks;
	}
	
	public synchronized void addTask(Task task) {
		if (!this.getTasks().containsKey(task.getMsgId())) {
			Logger.logInfo(this.getClass().getName(), "Se agrega el task asociado al mensaje "+task.getMsgId());
			this.getTasks().put(task.getMsgId(), task);
		} else {
			Logger.logInfo(this.getClass().getName(), "Ya se encuentra un task con ese id");
		}
	}
	
	public synchronized Task removeTask(String msgId) {
		if (this.getTasks().containsKey(msgId)) {
			Logger.logInfo(this.getClass().getName(), "Se remueve el task asociado al mensaje "+msgId);
			this.addTaskToHistory(msgId);
			return this.getTasks().remove(msgId);
		}
		Logger.logInfo(this.getClass().getName(), "No existe un task con ese id");
		return null;
	}
	
	/**
	 * Remueve un task y retorna los resultados que se recolectaron en este
	 * 
	 * @param msgId
	 * @return
	 */
	public synchronized Collection<Result> removeTaskAndGetResults(String msgId) {
		Task task = this.removeTask(msgId);
		if (task != null) {
			return task.getAllResults();
		} else return null;
	}
	
	public synchronized Collection<Result> getTaskResults(String msgId) {
		Task task = this.getTask(msgId);
		if (task != null) {
			return task.getAllResults();
		} else return null;
	}
	
	/**
	 * Para consultar si un task fue finalizado
	 * 
	 * @param msgId
	 * @return
	 */
	public synchronized boolean isTaskFinished(String msgId) {
		if (this.getTasks().containsKey(msgId)) {
			return this.getTasks().get(msgId).isFinished();
		} else {
			return false;
		}
	}
	
	/**
	 * Se agrega los resultados que fue devuelto por un peer con id peerId a un task con id msgId
	 * 
	 * @param msgId
	 * @param peerId
	 * @param results
	 */
	public synchronized void addResultsToTask(String msgId, String peerId, Collection<Result> results) {
		if (this.getTasks().containsKey(msgId)) {
			Logger.logInfo(this.getClass().getName(), "Se obtienen resultados al mensaje "+msgId+" por parte del peer "+peerId);
			this.getTasks().get(msgId).addPeerResults(peerId, results);
		} else {
			Logger.logInfo(this.getClass().getName(), "No existe entrada para el mensaje "+msgId);
		}
	}
	
	/**
	 * Se agrega un resultado que fue devuelto por un peer con id peerId a un task con id msgId
	 * 
	 * @param msgId
	 * @param peerId
	 * @param result
	 */
	public synchronized void addResultToTask(String msgId, String peerId, Result result) {
		Logger.logInfo(this.getClass().getName(), "Se obtiene un resultado al mensaje "+msgId+" por parte del peer "+peerId);
		if (this.getTasks().containsKey(msgId)) {
			this.getTasks().get(msgId).addPeerResult(peerId, result);
		}
	}
	
	/**
	 * Finalizado un task se agrega su id a la lista de históricos
	 * 
	 * @param msgId
	 */
	public synchronized void addTaskToHistory(String msgId){
		Logger.logInfo(this.getClass().getName(), "Se agrega al histórico el task asociado al mesaje "+msgId);
		this.getTasksHistory().add(msgId);
	}
	
	/**
	 * Consulta si el task ya fue finalizado
	 * 
	 * @param msgId
	 * @return 
	 */
	public synchronized boolean isTaskInHistory(String msgId) {
		return this.getTasksHistory().contains(msgId);
	}
	
	public synchronized Task getTask(String msgId) {
		if (this.getTasks().containsKey(msgId)) {
			return this.getTasks().get(msgId);
		} else return null;
	}
	
	public synchronized boolean containsTask(String msgId) {
		return this.getTasks().containsKey(msgId);
	}
	
}